-- Compiler
-- Create by weism
-- 编译相关的接口(如载入文件等)

-- 编译一个代码文件
function COMPILE(file)
    local f, err = loadfile(file);
    return f;
end

-- 编译并运行一个代码文件
function LOAD_RUN(file)
    return require(file);
end

-- 载入一个目录下的所有代码文件(list.lua指明了有哪些文件)
function LOAD_PATH(path)
    local file = path .. "/" .. "list";
    local r = LOAD_RUN(file);
    local f = {};
    for i = 1, #r do
        local bin = LOAD_RUN(path .. "/" .. r[i]);
        f[r[i]] = bin;
    end
    return f;
end

-- 载入一个目录下的所有代码文件(list.lua指明了有哪些文件)，只加载文件名，并不实际加载
function LOAD_PATH2(path)
    local file = path .. "/" .. "list";
    local r = LOAD_RUN(file);
    local f = {};
    for i = 1, #r do
        f[r[i]] = "TBL";
    end
    return f;
end

-- 卸载目录下的所有文件
function UNLOAD_PATH(path)
    local file = path .. "/" .. "list";
    local r = LOAD_RUN(file);
    local f = {};
    for i = 1, #r do
        package.loaded[path .. "/" .. r[i]] = nil;
    end    
    
    -- 回收内存
    collectgarbage("collect");
end

-- 重新载入指定文件
function update(file)
    local pos = string.find(file,"[^%/.]*$");
    local module_name = string.sub(file, pos);
    local mod = package.loaded[module_name];
    
    -- 若该文件为模块，且存在 destruct 方法，则先调用析构方法，再重新加载
    if type(mod) == "table" and type(mod.destruct) == "function" then
        (package.loaded[module_name]).destruct();
    end

    package.loaded[file] = false;
    require(file);

    mod = package.loaded[module_name];

    -- 若该文件为模块，且存在 destruct 方法，则先调用析构方法，再重新加载
    if type(mod) == "table" and type(mod.init) == "function" then
        mod.init();
    end

    -- 回收垃圾
    collectgarbage("collect"); 
end

-- 使用代码更新指定文件
function updateByScript(file, script)
    local pos = string.find(file,"[^%/.]*$");
    local module_name = string.sub(file, pos);
    local mod = package.loaded[module_name];
    
    -- 若该文件为模块，且存在 destruct 方法，则先调用析构方法，再重新加载
    if type(mod) == "table" and type(mod.destruct) == "function" then
        mod.destruct();
    end
    package.loaded[file] = false;

    -- 载入
    loadstring(script)();

    -- 若该文件为模块，且存在 destruct 方法，则先调用析构方法，再重新加载
    mod = package.loaded[module_name];
    if type(mod) == "table" and type(mod.init) == "function" then
        mod.init();
    end

    -- 回收垃圾
    collectgarbage("collect"); 
end
